package com.zhang.pdf.utils;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.spire.ms.System.Collections.IEnumerator;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.widget.PdfPageCollection;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

/**
 * 读取PDF文件
 * @author zhangyang
 *
 */
public class ReadPDF {
    /**
     * 临时图片
     */
    private final static String TMP_IMG = "D:/export/1.png";
    /**
     * tessdata文件目录
     */
    private final static String TESS_DATA_PATH = "D:/tessdata";
    
    
    
    public static void main(String args[]){

        try {
            readPdfBy9("d:/pdf/1.pdf");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TesseractException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取pdf文件，返回ExcelModel对象，单个pdf文件中有多个面单读取面单中第九个图片
     * @param str pdf的路径，每一个pdf中有10张图片
     * @throws IOException 
     * @throws MalformedURLException 
     * @throws TesseractException 
     */
    public static List<ExcelModel> readPdfBy9(String str) throws MalformedURLException, IOException, TesseractException{
        List<ExcelModel> list = new ArrayList<>(); 
        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(str);
        PdfPageCollection pages = doc.getPages();
        IEnumerator it = pages.iterator();
        int num = 1;
        while(it.hasNext()){
            PdfPageBase page = (PdfPageBase) it.next();
            //处理文字，取出需要的内容
            String texts = page.extractText();
            ExcelModel excelModel = getMsg(texts,false);
            if(excelModel != null){
                //先保存图片
                for (BufferedImage image : page.extractImages()) {
                    if(num == 9){
                        image = PngColoringUtil.changeBGColorSize4PNG(image, Color.WHITE);
                        fillImage(image);
                        PngDPIProcessor.process(image, 300, TMP_IMG);
                        num = 1;
                        break;
                    }
                    num++;
                }
                String orderNo = readImage();
                excelModel.setOrderNo(orderNo);
                list.add(excelModel);
            }
        }
        
        return list;
    }
    /**
     * 读取pdf文件，返回ExcelModel对象
     * @throws IOException 
     * @throws MalformedURLException 
     * @throws TesseractException 
     */
    public static List<ExcelModel> readPdfNoImg(String str) throws MalformedURLException, IOException, TesseractException{
        List<ExcelModel> list = new ArrayList<>(); 
        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(str);
        PdfPageCollection pages = doc.getPages();
        IEnumerator it = pages.iterator();
        while(it.hasNext()){
            PdfPageBase page = (PdfPageBase) it.next();
            //处理文字，取出需要的内容
            String texts = page.extractText();
            ExcelModel excelModel = getMsgJT(texts,false);
            list.add(excelModel);
        }
        
        return list;
    }

    /**
     * 读取指定目录下的指定图片
     * @throws TesseractException 
     */
    private static String readImage() throws TesseractException{
        File file = new File(TMP_IMG);
        ITesseract instance = new Tesseract();
        instance.setDatapath(TESS_DATA_PATH);
        instance.setTessVariable("user_defined_dpi", "300");
        instance.setLanguage("eng");
        String result = instance.doOCR(file);
        file.delete();
        
        return result;
    }
    /**
     * 提取收件人姓名，手机号，快递单号
     * @param resultantText
     * @param addr
     * @return
     */
    private static ExcelModel getMsg(String resultantText, boolean addr) {
        String tmp = new String(resultantText);
        ExcelModel excelModel = new ExcelModel();
        getPhoneNum(excelModel,resultantText);
        getSendNo(excelModel,resultantText);
        return excelModel;
    }
    /**
     * 提取收件人姓名，手机号，快递单号
     * @param resultantText
     * @param addr
     * @return
     */
    private static ExcelModel getMsgJT(String resultantText, boolean addr) {
        String tmp = new String(resultantText);
        ExcelModel excelModel = new ExcelModel();
        getPhoneNum(excelModel,resultantText);
        getSendNoYT2(excelModel,resultantText);
        return excelModel;
    }
    /**
     * 提取文本中的手机号和姓名
     * @param excelModel
     * @param text
     */
    private static void getPhoneNum(ExcelModel excelModel, String text){
        String regex="\\s1\\d{10}";
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            excelModel.setPhone(result);
            int end = matcher.end();
            int begin = text.lastIndexOf("\n", end);
            String str = text.substring(begin,end);
            if(str != null){
                str = str.trim();
                String[] strs = str.split(" ");
                if(strs.length > 1){
                    excelModel.setName(strs[0]);
                }
            }
            break;
        }
    }
    /**
     * 提取文本中的快递单号
     * @param excelModel
     * @param text
     */
    private static void getSendNo(ExcelModel excelModel, String text){
        String regex="\\d{4}\\s\\d{4}\\s\\d{4}\\s\\d";
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
    }
    /**
     * 提取文本中的快递单号
     * @param excelModel
     * @param text
     */
    private static void getSendNoJT(ExcelModel excelModel, String text){
        String regex="JT\\d{13}";
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
    }
    /**
     * 提取文本中的快递单号
     * @param excelModel
     * @param text
     */
    private static void getSendNoYT(ExcelModel excelModel, String text){
        String regex="YT\\d{13}";
        String regex2="\\d{4}\\s\\d{4}\\s\\d{4}\\s\\d";
        String regex3="\\d{14}";
        Pattern compile = Pattern.compile(regex);
        Matcher matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
        compile = Pattern.compile(regex2);
        matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
        compile = Pattern.compile(regex3);
        matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
    }
    private static void getSendNoYT2(ExcelModel excelModel, String text){
        String regex2="\\d{4}\\s\\d{4}\\s\\d{4}\\s\\d{3}";
        Pattern compile = Pattern.compile(regex2);
        Matcher matcher = compile.matcher(text);
        while (matcher.find()){
            String result = matcher.group();
            result = result.replace(" ", "");
            excelModel.setExpressNo(result);
            break;
        }
    }
    /**
     * 填充像素，如果某个像素周围的黑色像素大于等于3，则将其填充为黑色
     * @param image
     * @return
     */
    private static BufferedImage fillImage(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        for(int x=0;x<width;x++){
            for(int y=0;y<height;y++){
                //上，默认白色
                boolean p1b = false;
                //下，默认白色
                boolean p2b = false;
                //左，默认白色
                boolean p3b = false;
                //右，默认白色
                boolean p4b = false;
                if(y-1 >= 0){
                    int p = image.getRGB(x, y-1);
                    p1b = blackOrWhite(p);
                }
                if(y+1 < height){
                    int p = image.getRGB(x, y+1);
                    p2b = blackOrWhite(p);
                }
                if(x-1 >= 0){
                    int p = image.getRGB(x-1, y);
                    p3b = blackOrWhite(p);
                }
                if(x+1 < width){
                    int p = image.getRGB(x+1, y);
                    p4b = blackOrWhite(p);
                }
                //周围的黑色点大于等于3，将此点赋值为黑色
                if(isFill(p1b, p2b, p3b, p4b)){
                    image.setRGB(x, y, Color.BLACK.getRGB());
                }
            }
        }
        return image;
    }
    /**
     * 判断黑色的点是否大于等于3
     * @param p1b
     * @param p2b
     * @param p3b
     * @param p4b
     * @return
     */
    private static boolean isFill(boolean p1b,boolean p2b,boolean p3b,boolean p4b){
        int num = 0;
        if(p1b) num++;
        if(p2b) num++;
        if(p3b) num++;
        if(p4b) num++;
        return num >= 3;
    }
    /**
     * 
     * @param rgb
     * @return true 表示黑色，false表示白色
     */
    private static boolean blackOrWhite(int rgb){
        Color c = new Color(rgb);
        if(c.getRed() == 0 && c.getGreen() == 0 && c.getBlue() == 0){
            return true;
        }
        if(c.getRed() == 255 && c.getGreen() == 255 && c.getBlue() == 255){
            return false;
        }
        return false;
    }
}
